/*
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 *
 * Contributors: Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.core.internal.api;

import net.sourceforge.perforce.api.IError;
import net.sourceforge.perforce.api.IPerforceCommand;
import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.internal.Policy;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;

import java.util.Map;

/**
 * @version $Revision: 489 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 *
 *         TODO: Replace MultiStatus. Create MultiStatus by calling getCommand
 *         etc.
 */
public abstract class AbstractPerforceCommand implements IPerforceCommand {
  // ---------------------------------------------------------------------------
  // Private Variables

  /** Stores the status of the operation. */
  private MultiStatus status;
  /** Stores the progress monitor. */
  private IProgressMonitor monitor;

  // -------------------------------------------------------------------------
  // Public Constructors

  /**
   * Constructor for AbstractPerforceCommand.
   *
   * @param status the status object.
   */
  AbstractPerforceCommand(MultiStatus status) {
    this(status, null);
  }

  /**
   * Constructor for AbstractPerforceCommand.
   *
   * @param status the status object.
   * @param monitor the progress monitor.
   */
  AbstractPerforceCommand(MultiStatus status, IProgressMonitor monitor) {
    this.status = status;
    this.monitor = Policy.monitorFor(monitor);
  }

  // -------------------------------------------------------- Public Methods
  // (IClientUserDelegate)

  public boolean handleError(IError error) {
    String errorString = error.format(IError.EF_PLAIN | IError.EF_NOXLATE);
    switch (error.getSeverity()) {
      case IError.E_INFO:
        status.merge(PerforceStatus.decode(errorString, IStatus.INFO));
        break;

      case IError.E_WARN:
        status.merge(PerforceStatus.decode(errorString, IStatus.WARNING));
        break;

      default:
        status.merge(PerforceStatus.decode(errorString, IStatus.ERROR));
        break;
    }

    return true;
  }

  public String inputData(IError error) {
    throw new UnsupportedOperationException();
  }

  public boolean message(IError error) {
    if (error.isInfo()) {
      String infoString = error.format(IError.EF_PLAIN);
      outputInfo((char) ('0' + error.getGeneric()), infoString);
    } else {
      handleError(error);
    }

    return true;
  }

  public void outputError(String errorString) {
    status.merge(PerforceStatus.decode(errorString, IStatus.ERROR));
  }

  public void outputInfo(char level, String infoString) {
    status.merge(PerforceStatus.decode(infoString, IStatus.ERROR));
  }

  public void outputStat(Map<String, ?> strDict) {
    String message = String.format("Unexpected fstat on operation \"%s\"", getCommand());
    PerforceCorePlugin.log(new Status(IStatus.WARNING, PerforceCorePlugin.ID, message));
    System.out.println(strDict);
  }

  public void outputBinary(byte[] data) {

    unsupported(format("<binary data>"));
  }

  private void unsupported(String message) {
    message = getClass().getName() + "\n" + message;
    throw new UnsupportedOperationException(message);

  }

  private String format(String string) {
    return string;
  }

  public void outputText(byte[] data) {
    unsupported(format(data));
  }

  private String format(byte[] data) {
    return new String(data);
  }

  public void finished() {
  }

  // ----------------------------------------------------------- Public Methods
  // (IPerforceCommand)

  public IStatus getStatus() {
    return status;
  }

  // ---------------------------------------------------------------------------
  // Protected Methods

  /**
   * Call this method to retrieve the progress monitor.
   *
   * @return the progress monitor.
   */
  protected IProgressMonitor getProgressMonitor() {
    return monitor;
  }


  /**
   * Returns the associated MultiStatus object.
   *
   * @return the status object.
   */
  protected MultiStatus getMultiStatus() {
    return status;
  }

  /**
   * Sets a new value for MutliStatus.
   *
   * @param value the new value.
   */
  protected void setMultiStatus(MultiStatus value) {
    status = value;
  }
}
